package com.zijidelu.luframework.plugins.tomlock.core.utils;

import com.zijidelu.luframework.plugins.tomlock.core.annotation.TomLockMethod;
import com.zijidelu.luframework.plugins.tomlock.core.config.LockConstant;
import com.zijidelu.luframework.plugins.tomlock.core.exception.TomLockException;
import com.zijidelu.luframework.plugins.tomlock.core.handler.BaseTomLockHandler;
import org.apache.commons.codec.digest.DigestUtils;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

/**
 * @author ZIJIDELU
 * @datetime 2025/4/13 20:59
 */
public class TomLockUtil {
    /**
     * 计算分布式锁的KEY
     *
     * @param keys 键值列表
     * @return 分布式锁的KEY
     */
    public static String calcDistributedLockKey(Object... keys) {
        return DigestUtils.md5Hex(Arrays.stream(keys)
                .filter(Objects::nonNull)
                .map(Object::toString)
                .collect(Collectors.joining(LockConstant.LOCK_SPLIT))
        );
    }

    /**
     * 计算分布式锁的KEY
     *
     * @param keys 键值列表
     * @return 分布式锁的KEY
     */
    public static String calcDistributedLockKey(List<Object> keys) {
        return calcDistributedLockKey(keys.toArray());
    }

    /**
     * 计算方法签名
     *
     * @param handlerClass  分布式锁处理器类
     * @param methodName    方法名
     * @param paramTypeList 方法参数类型列表
     * @return 方法签名
     */
    public static String calcDistributedLockMethodSign(final Class<? extends BaseTomLockHandler> handlerClass,
                                                       final String methodName,
                                                       final List<? extends Class<?>> paramTypeList) {
        return DigestUtils.md5Hex(String.join(",",
                handlerClass.toString(),
                methodName,
                paramTypeList.stream().map(Class::toString).collect(Collectors.joining(LockConstant.LOCK_SPLIT))
        ));
    }

    /**
     * 搜索匹配的处理器计算锁的方法
     *
     * @param handlerClass 分布式锁处理器类
     * @param methodName   方法名
     * @param objectList   参数对象列表
     * @return 方法
     */
    public static Method searchMatchMethod(final Class<? extends BaseTomLockHandler> handlerClass,
                                           final String methodName,
                                           final List<Object> objectList) {
        // 获取处理器的处理方法
        final Method[] methods = handlerClass.getMethods();
        for (Method beanMethod : methods) {
            final TomLockMethod tomLockMethod = beanMethod.getAnnotation(TomLockMethod.class);
            final String beanMethodName = beanMethod.getName();
            // 匹配规则，方法存在指定注解，名称与注解设置的名称相同，参数数量一致，参数类型一致
            if (Objects.nonNull(tomLockMethod) && beanMethodName.equals(methodName)) {
                // 获取处理器方法参数类型
                final Class<?>[] parameterTypes = beanMethod.getParameterTypes();
                if (parameterTypes.length == objectList.size()) {
                    // 匹配参数类型
                    int count = 0;
                    for (int i = 0; i < objectList.size(); i++) {
                        if (parameterTypes[i] == (objectList.get(i).getClass())) {
                            count++;
                        }
                    }
                    // 参数类型，返回值类型匹配成功
                    if (count == objectList.size() && beanMethod.getReturnType() == Lock.class) {
                        return beanMethod;
                    }
                }
            }
        }

        throw new TomLockException(calcAnnoExceptionMessage("未在处理器中找到计算锁的方法，%s:%s(%s)",
                handlerClass,
                methodName,
                objectList.stream().map(Object::getClass).toList()
        ));
    }

    /**
     * 构建分布式锁注解异常信息
     *
     * @param desc     描述
     * @param messages 参数
     * @return 异常信息
     */
    public static String calcAnnoExceptionMessage(final String desc, final Object... messages) {
        return String.format("分布式锁注解：" + desc, messages);
    }


}
